﻿using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

namespace RoiControllers
{
    /// <summary> 形状基类  </summary>
    public abstract class ShapeBase:ShapeUpdateEvents
    {
        #region 字段、属性
        #region 字段
        private string _name = "形状";               //形状名称
        private string _description = "形状描述";    //形状描述
        protected RectangleF _rectangleF;            //形状（实际矩形）区域
        protected Color _backColor = Color.Blue;     //填充颜色
        protected Color _handleColor = Color.Orange; //手柄颜色
        protected Color _selectedColor = Color.Blue; //选中时的颜色
        protected Color _interestColor = Color.Red; //感兴趣颜色，不感兴趣时使用
        protected float _borderWidth = 0;            //边缘线宽
        protected byte _alpha = 20;                  //透明度            
        protected int _handleSize = 8;               //手柄的视觉大小
        protected int _handleOutSize = 16;           //手柄外区域大小(比视觉大)
        protected bool _isSelected = true;           //选中状态
        protected bool _isInterest = true;           //感兴趣状态
        protected bool isRotating = false;           //是否旋转
        protected PointF _lastLocation = PointF.Empty;   //位置
        protected ShapeType _type = ShapeType.None;  //形状类型
        protected ShapeHandleType _handleType;       //形状手柄类型    
        protected float _angle = 0F;       //形状手柄类型
        #endregion

        #region 属性
        /// <summary> 形状名称 </summary>
        [Category("用户属性")]
        [Description("形状名称")]
        public string Name { get => _name; set => _name = value; }
        /// <summary> 形状描述 </summary>
        [Category("用户属性")]
        [Description("形状描述")]
        public string Description { get => _description; set => _description = value; }
        /// <summary> 形状填充的背景颜色 </summary>
        [Category("用户属性")]
        [Description("形状填充的背景颜色")]
        public Color BackColor { get => _backColor; set => _backColor = value; }
        /// <summary> 形状手柄填充的颜色 </summary>
        [Category("用户属性")]
        [Description("形状手柄填充的颜色")]
        public Color HandleColor { get => _handleColor; set => _handleColor = value; }
        /// <summary> 选中形状时填充的颜色 </summary>
        [Category("用户属性")]
        [Description("选中形状时填充的颜色")]
        public Color SelectedColor { get => _selectedColor; set => _selectedColor = value; }
        /// <summary> 选中形状时填充的颜色 </summary>
        [Category("用户属性")]
        [Description("感兴趣颜色，感兴趣状态为False时的背景色")]
        public Color InterestColor {  get => _interestColor;  set => _interestColor = value;  }
        /// <summary> 边缘线宽</summary>
        [Category("用户属性")]
        [Description("边缘线宽")]
        public float BorderWidth { get => _borderWidth; set => _borderWidth = value; }
        /// <summary> 边缘线宽</summary>
        [Category("用户属性")]
        [Description("边缘线宽")]
        public float Angle { get => _angle; set => _angle = value; }

        /// <summary> 透明度</summary>
        [Category("用户属性")]
        [Description("透明度")]
        public byte Alpha { get => _alpha; set => _alpha = value; }
        /// <summary> 手柄大小</summary>
        [Category("用户属性")]
        [Description("手柄大小")]
        public int HandleSize
        {
            get => _handleSize;
            set
            {
                if (_handleSize != value)
                {
                    _handleSize = value;
                    HandleOutSize = value * 2;
                }
            }
        }
        /// <summary> 手柄扩增后大小</summary>
        [Category("用户属性")]
        [Description("手柄扩增后大小")]
        public int HandleOutSize
        {
            get => _handleOutSize;
            set
            {
                if (_handleOutSize != value)
                {
                    _handleOutSize = value;
                    _handleSize = value / 2;
                }
            }
        }
        /// <summary> 选中状态</summary>
        [Category("用户属性")]
        [Description("选中状态")]
        public bool IsSelected  { get => _isSelected; set => _isSelected = value;  }
        /// <summary> 选中状态</summary>
        [Category("用户属性")]
        [Description("感兴趣状态")]
        public bool IsInterest { get => _isInterest; set => _isInterest = value; }
        /// <summary> 最后位置 </summary>
        [Category("用户属性")]
        [Description("最后位置")]
        public PointF LastLocation { get => _lastLocation; set => _lastLocation = value; }
        /// <summary> 形状类型 </summary>
        [Category("用户属性")]
        [Description("形状类型")]
        public ShapeType Type { get=> _type; set => _type = value; }
        /// <summary> 旋转使能 </summary>
        [Category("用户属性")]
        [Description("旋转使能")]
        public bool IsRotating { get => isRotating; set => isRotating = value; }
        /// <summary> 手柄类型 </summary>
        [Category("用户属性")]
        [Description("手柄类型")]
        public ShapeHandleType HandleType { get => _handleType; set => _handleType = value; }
        /// <summary> 形状区域 </summary>
        [Category("用户属性")]
        [Description("形状区域")]
        public RectangleF Region { get => _rectangleF; set => _rectangleF = value; }
        /// <summary> 形状位置 </summary>
        [Category("用户属性")]
        [Description("形状位置")]
        public PointF Location { get => _rectangleF.Location; set => _rectangleF.Location = value;  }
        #endregion

        #region 事件方法
        /// <summary> 执行选中方法 </summary>
        public abstract void ExecuteSelectedCallback();
        /// <summary> 执行移动方法 </summary>
        public abstract void ExecuteMoveCallback();
        /// <summary> 执行旋转方法 </summary>
        public abstract void ExecuteRotateCallback();
        /// <summary> 执行调整大小方法 </summary>
        public abstract void ExecuteResizeCallback();
        /// <summary> 执行附加方法 </summary>
        public abstract void ExecuteAttachCallback();
        /// <summary> 执行移除方法 </summary>
        public abstract void ExecuteDetachCallback();
        #endregion
        #endregion

        #region 构造函数
        protected ShapeBase()
        {

        }
        protected ShapeBase(PointF point,int radius)
        {

        }
        protected ShapeBase(int x,int y,int width,int height)
        {

        }
        protected ShapeBase(double x, double y, double width, double height,double angle)
        {

        }
        #endregion

        #region 旋转计算相关
        /// <summary>
        /// 计算旋转后的矩形四个角点
        /// </summary>
        /// <param name="center">矩形中心点</param>
        /// <param name="width">矩形宽度</param>
        /// <param name="height">矩形高度</param>
        /// <param name="angle">旋转角度（度）</param>
        /// <returns>旋转后的四个角点数组</returns>
        public static PointF[] GetRotatedRectangleCorners(PointF center, float width, float height, float angle)
        {
            // 将角度转换为弧度
            float radians = angle * (float)Math.PI / 180f;
            float cos = (float)Math.Cos(radians);
            float sin = (float)Math.Sin(radians);
            // 计算半宽和半高
            float halfWidth = width / 2;
            float halfHeight = height / 2;
            // 四个角点相对于中心的初始位置（未旋转）
            PointF[] corners = new PointF[4];
            corners[0] = new PointF(-halfWidth, -halfHeight); // 左上
            corners[1] = new PointF(halfWidth, -halfHeight);  // 右上
            corners[2] = new PointF(halfWidth, halfHeight);    // 右下
            corners[3] = new PointF(-halfWidth, halfHeight);  // 左下
            // 旋转每个角点并加上中心坐标
            for (int i = 0; i < 4; i++)
            {
                // 应用旋转矩阵
                float x = corners[i].X * cos - corners[i].Y * sin;
                float y = corners[i].X * sin + corners[i].Y * cos;
                // 平移回中心位置
                corners[i] = new PointF(x + center.X, y + center.Y);
            }
            return corners;
        }

        /// <summary> 计算旋转后的矩形顶点 </summary>
        public PointF[] GetRotatedRectangleCorners(RectangleF rect, float angleDegrees)
        {
            PointF center = new PointF(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
            float angleRadians = angleDegrees * (float)Math.PI / 180f;
            PointF[] corners = new PointF[4];
            corners[0] = RotatePoint(new PointF(rect.X, rect.Y), center, angleRadians);
            corners[1] = RotatePoint(new PointF(rect.X + rect.Width, rect.Y), center, angleRadians);
            corners[2] = RotatePoint(new PointF(rect.X + rect.Width, rect.Y + rect.Height), center, angleRadians);
            corners[3] = RotatePoint(new PointF(rect.X, rect.Y + rect.Height), center, angleRadians);
            return corners;
        }
        /// <summary>旋转点</summary>
        /// <param name="pointToRotate">需要旋转的点 </param>
        /// <param name="centerPoint">旋转中心点</param>
        /// <param name="angleInDegrees">旋转角度(以度为单位) </param>
        /// <return>返回旋转后的新点坐标。</return>
        public PointF RotatePoint(PointF point, PointF center, float angleInDegrees)
        {
            float angleInRadians = angleInDegrees * (float)Math.PI / 180f;
            float cosTheta = (float)Math.Cos(angleInRadians);
            float sinTheta = (float)Math.Sin(angleInRadians);
            float dx = point.X - center.X;
            float dy = point.Y - center.Y;
            return new PointF(dx * cosTheta - dy * sinTheta + center.X, dx * sinTheta + dy * cosTheta + center.Y);
        }
        #endregion

        #region 其他方法
        /// <summary> 获取类型形状，输出形状数据 </summary>
        public void GetTypeShape(ShapeType type, out double[] data)
        {
            switch (type)
            {
                case ShapeType.Rectangle:
                    data = new double[4];
                    URectangle rectangle = this as URectangle;
                    data[0] = rectangle.X;
                    data[1] = rectangle.Y;
                    data[2] = rectangle.Width;
                    data[3] = rectangle.Height;
                    return;
                case ShapeType.Rectangle2:
                    data = new double[5];
                    URectangle2 rectangle2 = this as URectangle2;
                    data[0] = rectangle2.X;
                    data[1] = rectangle2.Y;
                    data[2] = rectangle2.Width;
                    data[3] = rectangle2.Height;
                    data[4] = rectangle2.RotationAngle;
                    return;
                case ShapeType.Circle:
                    data = new double[3];
                    URCircle circle = this as URCircle;
                    data[0] = circle.Center.X;
                    data[1] = circle.Center.Y;
                    data[2] = circle.Radius;
                    return;
                case ShapeType.Ellipse:
                    data = new double[5];
                    return;
                case ShapeType.Polygon:
                    data = new double[5];
                    return;
                case ShapeType.None:
                    data = new double[5];
                    return;
                default:
                    throw new ArgumentException("Unknown shape type");
            }
        }
        /// <summary> 获取类型形状，返回对应形状对象实例 </summary>
        public T GetTypeShape<T>(ShapeType type) where T : ShapeBase
        {
            try
            {
                return this as T;
            }
            catch (Exception)
            {
                throw new ArgumentException("Unknown shape type");
            }
        }
        /// <summary> 创建形状对象：根据输入的形状类型和位置 </summary>
        public static ShapeBase CreateShapeObject(ShapeType type,PointF point)
        {
            switch (type)
            {
                case ShapeType.Rectangle:
                    return new URectangle(point.X, point.Y, 50, 50);
                case ShapeType.Rectangle2:
                    return new URectangle2(point.X, point.Y, 50, 50, 0);
                case ShapeType.Circle:
                    return new URCircle(point, 50);
                default:
                    return new URectangle((int)point.X, (int)point.Y, 50, 50);
            }
        }
        /// <summary> 绘制带手柄的形状 ：绘制输入矩形，绘制完成后恢复原来位置</summary>
        public void DrawShapeWithHandle(Graphics graphics, RectangleF rect)
        {
            RectangleF tempRect = Region;
            Region = rect;
            DrawShapeWithHandle(graphics);
            Region = tempRect;
        }
        /// <summary> 移动并保存最后位置，1转换点，2是实际点</summary>
        public void Move(PointF pointF1,PointF pointF2)
        {
            Move(pointF1);
            LastLocation = pointF2;
        }
        /// <summary> 调整大小并保存最后位置，1转换点，2是实际点</summary>
        public void Resize(PointF pointF1, PointF pointF2)
        {
            Resize(pointF1);
            LastLocation = pointF2;
        }
        #endregion

        #region 抽象方法：绘制形状相关方法。
        /// <summary> 调整形状角度 </summary>
        public abstract void Rotate(PointF point);
        /// <summary> 调整形状位置 </summary>
        public abstract void Move(PointF point);
        /// <summary> 调整形状大小 </summary>
        public abstract void Resize(PointF point);
        /// <summary> 绘制形状带手柄：选中时绘制手柄，未选中时绘制轮廓 </summary>
        public abstract void DrawShapeWithHandle(Graphics graphics);
        /// <summary>绘制形状手柄 </summary>
        public abstract void DrawHandle(Graphics graphics, float x, float y);
        /// <summary>绘制形状手柄 </summary>
        public abstract void DrawHandle(Graphics graphics, PointF point);
        /// <summary> 获取要显示的自定义手柄类型：根据输入点</summary>
        public abstract ShapeHandleType GetHandleType(PointF point);
        /// <summary> 获取系统自带的手柄类型：根据输入点 </summary>
        public abstract Cursor GetSystemHandleType(PointF point);
        /// <summary> 输入点是否在矩形区域内 </summary>
        public abstract bool IsInRegion(PointF point);
        /// <summary> 输入点是否在矩形背景区域内（仅背景，不包括手柄交集） </summary>
        public abstract bool IsInBackground(PointF point);
        /// <summary> 输入点是否在手柄范围内（输入点，所在点（中心）） </summary>
        public abstract bool IsInHandle(PointF inPoint, PointF point);
        /// <summary> 输入点是否在旋转手柄范围内 </summary>
        public abstract bool IsInRotateHandle(PointF point);
        #endregion
    }

    #region 枚举类型
    /// <summary> 手柄类型 </summary>
    public enum ShapeHandleType
    {
        None,
        [Description("旋转")]
        Rotation,
        [Description("中心")]
        Center,
        [Description("内部")]
        Inner,
        [Description("左")]
        Left,
        [Description("上")]
        Top,
        [Description("右")]
        Right,
        [Description("下")]
        Bottom,
        [Description("左上")]
        TopLeft,
        [Description("右上")]
        TopRight,
        [Description("左下")]
        BottomLeft,
        [Description("右下")]
        BottomRight
    }
    /// <summary> 形状类型  </summary>
    public enum ShapeType
    {
        [Description("矩形")]
        Rectangle,
        [Description("方向矩形")]
        Rectangle2,
        [Description("圆形")]
        Circle,
        [Description("椭圆形")]
        Ellipse,
        [Description("多边形")]
        Polygon,
        [Description("None")]
        None
    }
    /// <summary> 形状操作模式 </summary>
    public enum ShapeOperateMode
    {
        /// <summary> None</summary>
        None,
        /// <summary>绘制</summary>
        [Description("绘制")]
        Drawing,
        /// <summary>选中</summary>
        [Description("选中")]
        Selected,
        /// <summary>移动</summary>
        [Description("移动")]
        Move,
        /// <summary>缩放</summary>
        [Description("缩放")]
        Scaled,
        /// <summary>旋转</summary>
        [Description("旋转")]
        Rotote,
        /// <summary>调整大小</summary>
        [Description("调整大小")]
        Resize,
    }
    #endregion
}
